﻿using Microsoft.IdentityModel.Tokens;
using RbacPermissionSystem.Application.Admins.Dto;
using RbacPermissionSystem.Domain;
using RbacPermissionSystem.Repositories;
using RbacPermissionSystem.Utility;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Security;
using System.Text;
using IdentityModel;
using Microsoft.Extensions.Configuration;
using Microsoft.EntityFrameworkCore;
using AutoMapper;
using Microsoft.AspNetCore.Http;
using System.Net.Http;

namespace RbacPermissionSystem.Application.Admins
{
    public class AdminService : IAdminService
    {
        private readonly IRepository<Admin> repository;
        private readonly IConfiguration configuration;
        private readonly IMapper mapper;
        private readonly IHttpContextAccessor httpContext;

        public AdminService(IRepository<Admin> repository, IConfiguration configuration, IMapper mapper, IHttpContextAccessor httpContext)
        {
            this.repository = repository;
            this.configuration = configuration;
            this.mapper = mapper;
            this.httpContext = httpContext;
        }

        /// <summary>
        /// 注册
        /// </summary>
        /// <param name="registerDto"></param>
        /// <returns></returns>
        public async Task<ResultDto> Register(RegisterDto registerDto)
        {
            //....验证码

            //查用户
            var admin = await repository.FirstOrDefaultAsync(m => m.UserName == registerDto.UserName);
            if (admin != null)
            {
                return new ResultDto { Code = Code.Failed, Message = "用户名已使用" };
            }

            //MD5加密

            Admin admin1 = new Admin
            {
                UserName = registerDto.UserName,
                Password = registerDto.Password.Md5(),
                CreaterName = "zs",
                CreaterTime = DateTime.Now
            };

            try
            {
                await repository.InsertAsync(admin1);
                return new ResultDto { Code = Code.Success };
            }
            catch (Exception e)
            {
                return new ResultDto { Code = Code.Failed, Message = e.Message };
            }
        }

        /// <summary>
        /// 添加
        /// </summary>
        /// <param name="createDto"></param>
        /// <returns></returns>
        public async Task<ResultDto> CreateAsync(AdminCreateDto createDto)
        {
            //查用户
            var isExists = await repository.FirstOrDefaultAsync(m => m.UserName == createDto.UserName);
            if (isExists != null)
            {
                return new ResultDto { Code = Code.Failed, Message = "用户名已使用" };
            }

            //MD5加密

            Admin admin = mapper.Map<AdminCreateDto, Admin>(createDto);
            admin.Password = admin.Password.Md5();
            var user = httpContext.HttpContext.User;

            var claims = httpContext.HttpContext.User.Claims;

            admin.CreaterName = httpContext.HttpContext.User.Identity.Name;
            admin.CreaterTime = DateTime.Now;

            try
            {
                await repository.InsertAsync(admin);
                return new ResultDto { Code = Code.Success };
            }
            catch (Exception e)
            {
                return new ResultDto { Code = Code.Failed, Message = e.Message };
            }
        }

        /// <summary>
        /// 更新
        /// </summary>
        /// <param name="updateDto"></param>
        /// <returns></returns>
        public async Task<ResultDto> UpdateAsync(AdminUpdateDto updateDto)
        {
            //查用户
            var isExists = await repository.FirstOrDefaultAsync(m => m.UserName == updateDto.UserName && m.AdminId != updateDto.AdminId);
            if (isExists != null)
            {
                return new ResultDto { Code = Code.Failed, Message = "用户名已使用" };
            }

            Admin entity = await repository.FindAsync(updateDto.AdminId);

            Admin admin = mapper.Map(updateDto, entity);

            admin.UpdateName = httpContext.HttpContext.User.Identity.Name;
            admin.UpdateTime = DateTime.Now;

            try
            {
                await repository.UpdateAsync(entity);
                return new ResultDto { Code = Code.Success };
            }
            catch (Exception e)
            {
                return new ResultDto { Code = Code.Failed, Message = e.Message };
            }
        }

        /// <summary>
        /// 根据id获取adminDTO
        /// </summary>
        /// <param name="AdminId"></param>
        /// <returns></returns>
        public async Task<ResultDto<AdminListDto>> GetAsync(int AdminId)
        {
            var admin = await repository.FindAsync(AdminId);
            return new ResultDto<AdminListDto> { Code = Code.Success, Data = mapper.Map<Admin,AdminListDto>(admin) };
        }

        /// <summary>
        /// 单删
        /// </summary>
        /// <param name="AdminId"></param>
        /// <returns></returns>
        public async Task<ResultDto<bool>> DeleteAsync(int AdminId)
        {
            try
            {
                await repository.DeleteAsync(AdminId);
                return new ResultDto<bool> { Code = Code.Success, Data = true };
            }
            catch (Exception e)
            {
                return new ResultDto<bool> { Code = Code.Failed, Data = false, Message = e.Message };
            }
        }

        /// <summary>
        /// 批删
        /// </summary>
        /// <param name="AdminId"></param>
        /// <returns></returns>
        public async Task<ResultDto<bool>> DeleteAsync(List<int> adminIds)
        {
            try
            {
                await repository.DeleteAsync(adminIds);
                return new ResultDto<bool> { Code = Code.Success, Data = true };
            }
            catch (Exception e)
            {
                return new ResultDto<bool> { Code = Code.Failed, Data = false, Message = e.Message };
            }
        }

        /// <summary>
        /// 登录
        /// </summary>
        /// <param name="loginDto"></param>
        /// <returns></returns>
        public async Task<LoginResultDto<string>> LoginAsync(LoginDto loginDto)
        {
            var admin = await repository.FirstOrDefaultAsync(m => m.UserName == loginDto.UserName);
            if(admin == null)
            {
                return new LoginResultDto<string> { Code = LoginEnum.NoAccount, Message = LoginEnum.NoAccount.EnumToDescription() };
            }
            else
            {
                if(admin.Password != loginDto.Password.Md5())
                {
                    return new LoginResultDto<string> { Code = LoginEnum.PasswordError, Message = LoginEnum.PasswordError.EnumToDescription() };
                }
                else
                {
                    //生成Token
                    IList<Claim> claims = new List<Claim> {
                                new Claim(JwtClaimTypes.Id, admin.AdminId.ToString()),
                                new Claim(JwtClaimTypes.Name, admin.UserName)
                            };

                    //JWT密钥
                    var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuration["JwtConfig:Bearer:SecurityKey"]));

                    //签名证书
                    var cred = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

                    //过期时间
                    DateTime expires = DateTime.UtcNow.AddMinutes(300);

                    //Payload负载
                    var token = new JwtSecurityToken(
                        issuer: configuration["JwtConfig:Bearer:Issuer"],
                        audience: configuration["JwtConfig:Bearer:Audience"],
                        claims: claims,
                        notBefore: DateTime.UtcNow,
                        expires: expires,
                        signingCredentials: cred
                        );

                    var handler = new JwtSecurityTokenHandler();

                    //生成令牌
                    string jwt = handler.WriteToken(token);

                    return new LoginResultDto<string> { Code = LoginEnum.Success, Data = jwt };
                }
            }
        }

        public async Task<ResultDto<(int, List<AdminListDto>)>> PageAsync(AdminSearchDto searchDto,int PageIndex = 1,int PageSize = 10)
        {
            var list = repository.Queryable();

            if (!string.IsNullOrEmpty(searchDto.Keywords))
            {
                list = list.Where(m => m.UserName.Contains(searchDto.Keywords) || m.Email.Contains(searchDto.Keywords));
            }

            if(searchDto.StartTime != null)
            {
                list = list.Where(m => m.CreaterTime >= searchDto.StartTime);
            }

            if (searchDto.EndTime != null)
            {
                list = list.Where(m => m.CreaterTime <= searchDto.EndTime);
            }

            var PageData = await list.OrderByDescending(m => m.CreaterTime).Skip((PageIndex - 1) * PageSize).Take(PageSize).ToListAsync();


            var result = mapper.Map<List<Admin>, List<AdminListDto>>(PageData);

            //查询条件
            return new ResultDto<(int, List<AdminListDto>)> { Data = (await list.CountAsync(), result) };
            
        }
    }
}